package myJs.user.blast

import myJs.Implicits._
import myJs.Utils
import myJs.Utils._
import myJs.myPkg._
import myJs.myPkg.jquery._
import myJs.tool.Pojo.FilterContentData
import myJs.tool.Tool
import org.scalajs.dom._
import org.scalajs.dom.ext.Ajax
import scalatags.Text.all._

import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.JSON
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import myJs.FileSaver

/**
 * Created by yz on 16/9/2021
 */
@JSExportTopLevel("Blastn")
object Blastn {

  val formId = "form"
  var tableData: String = _
  var layerIndex: Int = _

  @JSExport("init")
  def init = {
    Tool.fileInput
    refreshDb
    bootStrapValidator
    registerEvent
  }

  def refreshDb = {
    val inputName = "db"
    val url = g.jsRoutes.controllers.DataController.getAllSample().url.toString
    Ajax.get(url = s"${url}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val rs = xhr.responseText.toJArJDJAn
      val array = rs.map { dict =>
        js.Dictionary("text" -> dict.myGet("sampleName"), "id" -> dict.myGet("id"))
      }
      val options = Select2Options.dictData(array.toJSArray).multiple(false)
      Tool.getInputByName(inputName).mySelect2(options)
    }
  }

  def registerEvent = {
    $(document.body).on("change fileclear", s".file", "", (y: Element) => {
      $(y).parents("form").bv.revalidateField("file")
    })
    $(document.body).on("click", s".myRun", "", (y: Element) => {
      myRun
    })
    $(document.body).on("click", s".myShowExample", "", (y: Element) => {
      showExample(y)
    })
    $(document.body).on("click", s".myDownloadXls", "", (y: Element) => {
      downloadXls
    })
    $(document.body).on("change", s".myMethodChange", "", (y: Element) => {
      methodChange(y)
    })
    window.addEventListener("message", (e: Event) => {
      val me = e.asInstanceOf[MessageEvent]
      if (me.data.toString == "success") {
        layer.close(layerIndex)
        $("#result").show()
        val target_top = $("#result").offset().top
        $("html,body").animate(js.Dictionary("scrollTop" -> target_top), JQueryAnimationSettings.duration(800))
      }
    }, false)
  }

  def methodChange(y: Element) = {
    val myValue = $(y).find(">option:selected").`val`().toString
    myValue match {
      case "text" =>
        $("#queryContent").show()
        $("#queryFile").hide()
      case _ =>
        $("#queryContent").hide()
        $("#queryFile").show()
    }
  }

  def showExample(y: Element) = {
    val inputJq = $(y).parents(".form-group").find(":input")
    val str =
      s"""
         |>Example1
         |ATGGTGAAAGTGTATGCCCCGGCTTCCAGCGCGAACATGAGCGTCGGTTTCGACGTGTTGGGCGCGGCCGTCACACCCGTTGACGGCACGTTGCTGGGCGATGTGGTATCCGTTGAAGCAGCGGATCATTTCCGTCTGCATAACCTGGGGCGATTTGCCGATAAACTGCCGCCGGAGCCGCGTGAAAATATTGTTTATCAGTGCTGGGAACGTTTTTGCCAGGCATTGGGGAAAACCATCCCGGTGGCGATGACGCTGGAAAAAAATATGCCGATTGGTTCCGGGTTAGGGTCCAGCGCCTGTTCCGTCGTCGCCGCGCTGGTCGCGATGAATGAGCACTGCGGCAAACCGTTAAACGACACGCGTCTGTTGGCGCTGATGGGCGAGCTGGAAGGCCGTATCTCCGGCAGCATCCATTACGATAACGTCGCGCCGTGCTTTCTTGGCGGTATGCAGTTGATGATTGAAGAAAACGGCATTATTAGTCAGCAGGTGCCGGGCTTTGATGAGTGGCTATGGGTACTGGCTTATCCGGGCATTAAAGTTTCCACCGCAGAAGCACGGGCCATTTTGCCTGCGCAGTATCGCCGTCAGGATTGCATTGCGCATGGACGGCATCTGGCCGGTTTTATTCACGCCTGTTACTCGCGGCAGCCGCAGCTTGCCGCCGCGCTGATGAAAGATGTTATTGCCGAACCATACCGCGCGCGTTTACTGCCGGGCTTTAGCCAGGCGCGGCAGGCGGTGTCGGAGATCGGCGCGCTGGCGAGCGGGATTTCCGGATCGGGGCCGACGCTGTTTGCGCTATGCGATAAACCGGAGACGGCGCAGCGCGTCGCGGACTGGCTGAGCAAACATTATCTGCAAAATCAGGAAGGCTTCGTTCATATTTGTCGGCTGGATACGGCGGGCGCACGAGTAGTGGGATAA
         |>Example2
         |ATGCGAGTGTTGAAGTTCGGCGGTACATCAGTGGCAAATGCAGAACGTTTTCTGCGTGTTGCCGATATTCTGGAAAGCAATTCCAGGCAAGGGCAGGTAGCGACCGTACTTTCCGCCCCCGCGAAAATTACCAACCATCTGGTGGCGATGATTGAAAAAACTATCGGCGGCCAGGATGCTTTGCCGAATATCAGCGATGCCGAACGTATTTTTTCTGACCTGCTCGCAGGACTTGCCAGCGCGCAGCCGGGATTCCCGCTTGCACGGTTGAAAATGGTTGTCGAACAAGAATTCGCTCAGATCAAACATGTTTTGCATGGTATCAGCCTGCTGGGTCAGTGCCCGGATAGCATCAACGCCGCGCTGATTTGCCGTGGCGAAAAAATGTCGATCGCGATTATGGCGGGACTCCTGGAGGCGCGTGGACATCGCGTCACGGTGATCGATCCGGTAGAAAAACTGCTGGCGGTGGGCCATTACCTTGAATCTACCGTCGATATCGCGGAATCGACTCGCCGTATCGCCGCCAGCCAGATCCCGGCCGATCACATGATCCTGATGGCGGGCTTTACTGCCGGTAATGAAAAGGGTGAACTGGTGGTGCTGGGCCGTAATGGTTCCGACTATTCCGCCGCCGTGCTGGCCGCCTGTTTACGCGCTGACTGCTGTGAAATCTGGACTGACGTCGATGGCGTGTATACCTGTGACCCGCGCCAGGTGCCGGACGCCAGGCTGTTGAAATCGATGTCCTACCAGGAAGCGATGGAGCTCTCTTACTTCGGCGCTAAAGTCCTTCACCCTCGCACCATAACGCCTATCGCCCAGTTCCAGATCCCCTGTCTGATTAAAAATACCGGCAATCCGCAGGCGCCAGGAACGCTGATCGGCGCGTCCAGCGACGATGATAATCTGCCGGTTAAAGGGATCTCTAACCTTAACAACATGGCGATGTTTAGCGTCTCCGGCCCGGGAATGAAAGGGATGATTGGGATGGCGGCGCGTGTTTTCGCCGCCATGTCTCGCGCCGGGATCTCGGTGGTGCTCATTACCCAGTCCTCCTCTGAGTACAGCATCAGCTTCTGTGTGCCGCAGAGTGACTGCGCGCGTGCCCGCCGTGCGATGCAGGATGAGTTCTATCTGGAGCTGAAAGAGGGGCTGCTGGAGCCGCTGGCGGTTACGGAGCGGTTGGCGATTATCTCTGTTGTCGGCGACGGTATGCGCACGCTACGCGGCATTTCAGCGAAATTCTTCGCCGCGCTGGCGCGGGCTAATATCAATATCGTGGCGATCGCTCAGGGATCTTCTGAGCGTTCCATTTCTGTGGTGGTGAATAACGACGATGCCACCACCGGCGTGCGGGTAACGCACCAGATGCTGTTCAATACCGATCAGGTGATTGAAGTGTTTGTCATTGGCGTCGGCGGCGTCGGCGGCGCGCTACTGGAACAGCTTAAACGTCAGCAAACCTGGCTGAAGAACAAGCACATCGATCTACGCGTGTGCGGCGTGGCGAACTCAAAGGCGTTGCTAACCAATGTGCATGGCCTGAATCTGGACAACTGGCAGGCGGAACTGGCGCAAGCGAACGCGCCGTTCAATCTGGGACGTTTAATTCGCCTGGTGAAAGAATATCATCTACTCAATCCGGTGATTGTTGATTGTACCTCCAGTCAGGCGGTGGCCGACCAGTATGCCGACTTCCTGCGCGAAGGGTTCCATGTGGTGACGCCGAACAAGAAAGCGAACACCTCGTCGATGGACTACTACCATCAGCTACGTTTCGCCGCCGCGCAATCACGGCGCAAATTCTTGTATGACACCAACGTCGGCGCCGGTTTGCCGGTAATCGAAAACCTGCAAAACCTGCTGAATGCGGGTGATGAACTGCAAAAATTTTCCGGCATTCTTTCCGGGTCGCTCTCTTTTATTTTCGGTAAACTGGAAGAGGGGATGAGTCTCTCACAGGCGACCGCTCTGGCGCGCGAGATGGGCTATACCGAACCCGATCCGCGCGACGATCTTTCCGGTATGGATGTGGCGCGTAAACTGTTGATCCTCGCCCGCGAGACGGGCCGCGAGCTGGAGCTTTCCGATATCGTGATTGAACCGGTGTTGCCGGACGAGTTTGACGCCTCCGGCGATGTGACCGCCTTTATGGCGCATCTGCCGCAGCTTGACGACGCGTTTGCCGCCCGTGTGGCGAAAGCTCGTGATGAAGGTAAGGTATTGCGCTATGTGGGCAATATCGAAGAGGATGGCGTGTGCCGCGTGAAGATTGCCGAAGTTGATGGTAACGATCCGCTCTTCAAAGTGAAAAACGGTGAAAACGCGCTGGCGTTCTACAGCCATTATTATCAGCCCTTGCCGTTGGTGCTGCGCGGCTACGGCGCAGGCAATGATGTGACGGCGGCGGGCGTGTTTGCCGATCTGTTACGGACCCTCTCATGGAAGTTAGGAGTTTAA
         |""".stripMargin.trim
    inputJq.`val`(str)
    $(s"#${formId}").bv.revalidateField("queryText")
  }

  def myRun = {
    val formJq = $("#form")
    val bv = formJq.bv
    bv.validate()
    val valid = bv.isValid()
    if (valid) {
      val element = div(id := "content",
        span(id := "info", "文件上传中",
          span(id := "progress")), " ",
        img(src := "/assets/images/running2.gif", cls := "runningImage", width := 30, height := 20)
      ).render
      val layerOptions = LayerOptions.icon(16).shade(0.01).time(20000000)
      layerIndex = layer.msg(element, layerOptions)
      val formData = new FormData(formJq(0).toHTMLFormElement)
      val url = g.jsRoutes.controllers.BlastController.blastn().url.toString
      val xhr = new XMLHttpRequest
      xhr.open("post", url)
      xhr.upload.onprogress = Utils.progressHandlingFunction
      xhr.onreadystatechange = (e) => {
        if (xhr.readyState == XMLHttpRequest.DONE) {
          val rs = xhr.responseText.toJDJAn
          val valid = rs("valid").toB
          if (valid) {
            tableData = rs.myGet("tableData")
            val url = g.jsRoutes.controllers.BlastController.blastResultBefore().url.toString
            val id = Tool.getInputByName("db").myVal
            $("#frame").attr("src", s"${url}?path=${rs("path")}&id=${id}")
          } else {
            layer.close(layerIndex)
            g.swal("Error", rs.myGet("message"), "error")
            $("#result").hide()
          }
        }
      }
      xhr.send(formData)
    }
  }

  def downloadXls = {
    val fileName = "blast.xls"
    val content = tableData
    val blob = new Blob(js.Array(content),
      BlobPropertyBag(`type` = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"))
    FileSaver.saveAs(blob, fileName)
  }

  def bootStrapValidator = {
    val maxNumber = Double.MaxValue
    val dict: js.Dictionary[js.Any] = js.Dictionary(
      "feedbackIcons" -> js.Dictionary(
        "valid" -> "glyphicon glyphicon-ok",
        "invalid" -> "glyphicon glyphicon-remove",
        "validating" -> "glyphicon glyphicon-refresh",
      ),
      "fields" -> js.Dictionary(
        "queryText" -> {
          val info = "Query文本"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空！"
              ),
            )
          )
        },
        "file" -> {
          val info = "Query文件"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空！"
              ),
              "file" -> js.Dictionary(
                "message" -> s"${info}格式不正确（*.fa,*.fasta）！",
                "extension" -> "fa,fasta",
              ),
            )
          )
        },
        "evalue" -> {
          val info = "Evalue"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空！"
              ),
              "numeric" -> js.Dictionary(
                "message" -> s"${info}必须为实数！",
              ),
              "between" -> js.Dictionary(
                "min" -> 0,
                "max" -> maxNumber,
                "inclusive" -> false,
                "message" -> s"${info}必须大于等于0",
              ),
            )
          )
        },
        "wordSize" -> {
          val info = "Word size"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空！"
              ),
              "integer" -> js.Dictionary(
                "message" -> s"${info}必须为自然数！",
              ),
              "between" -> js.Dictionary(
                "min" -> 4,
                "max" -> maxNumber,
                "inclusive" -> false,
                "message" -> s"${info}必须大于等于4",
              ),
            )
          )
        },
        "maxTargetSeqs" -> {
          val info = "Max target seqs"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空！"
              ),
              "integer" -> js.Dictionary(
                "message" -> s"${info}必须为自然数！",
              ),
              "between" -> js.Dictionary(
                "min" -> 0,
                "max" -> maxNumber,
                "inclusive" -> false,
                "message" -> s"${info}必须大于等于0",
              ),
            )
          )
        },
        "db" -> {
          val info = "核酸序列数据库"
          js.Dictionary(
            "validators" -> js.Dictionary(
              "notEmpty" -> js.Dictionary(
                "message" -> s"${info}不能为空！"
              ),
            )
          )
        },
      )
    )
    $(s"#form").bootstrapValidator(dict)
  }


}
